#include "FileManager.h"


#define WHERESTR  "Error[file %s, line %d]: "
#define WHEREARG  __FILE__, __LINE__

/*
 * Open and read a HDF5 file 
 * Parameters:
 * 		IN	file_name	: 	HDF5 file's name
 * 		IN	dataset_name	:	dataset's name
 *		OUT	dim		:	DataSpace's dimension
 *		OUT     volume		:	Voleme read
 *
 * Example of usage:
 * float *** volume;
 * hsize_t   dim[3];
 * readHDF5("FILE", "DATASET", &dim[0], &volume);
 * 
 */

int readHDF5(const char * file_name, const char * dataset_name, volume_t * volume)
{
	herr_t 		status;
	hid_t 		file_id;
	hid_t 		dataset_id;
	hid_t 		spaceid;
	int		ndim;
	hsize_t		dims[3];

	if ((file_id	= H5Fopen(file_name, H5F_ACC_RDWR, H5P_DEFAULT)) < 0)
	{
		fprintf(stderr, WHERESTR" unable to open the requested file\n",WHEREARG);
		return -1;
	}

	if ((dataset_id	= H5Dopen(file_id, dataset_name)) < 0 )
	{
		fprintf(stderr, WHERESTR" unable to open the requested data set\n",WHEREARG);
		return -1;
	}

	if ((spaceid	= H5Dget_space(dataset_id)) < 0)
	{
		fprintf(stderr, WHERESTR" unable to open the requested data space\n",WHEREARG);
		return -1;
	}

	if ((ndim	= H5Sget_simple_extent_dims (spaceid, dims, NULL)) < 0)
	{
		fprintf(stderr, WHERESTR" handling file\n",WHEREARG);
                return -1;
	}

	if ( createVolume(volume, dims) < 0)
	{
		fprintf(stderr, WHERESTR" Creating the volume\n",WHEREARG);
                return -1;
	}


	if ((status = H5Dread(dataset_id, H5T_IEEE_F32LE, spaceid/*H5S_ALL*/, H5S_ALL, H5P_DEFAULT, volume->memory)) < 0)
	{
		fprintf(stderr, WHERESTR" unable to read the file\n",WHEREARG);
                return -1;
	}

	if ((status = H5Dclose(dataset_id)) < 0)
	{
                fprintf(stderr, WHERESTR" unable to close the data set\n",WHEREARG);
                return -1;
        }

	if ((status = H5Fclose(file_id)) < 0);
	{
                fprintf(stderr, WHERESTR" unable to close the file\n",WHEREARG);
                //return -1;
		/*
		 * XXX cduelo: No entiendo porque falla al cerrar el fichero....
		 *
		 */
        }

	return 0;
}

int CreateFile(volume_t * volume, char * newname, char * dataset_name, int x, int y, int z)
{

	hid_t       file, dataset;         /* file and dataset handles */
	hid_t       datatype, dataspace;   /* handles */
	hsize_t     dimsf[3];              /* dataset dimensions */
	herr_t      status;
	int         i, j, k;
	int 	    aux = 0;

	float * data = (float*) malloc(x*y*z*sizeof(float));
	
	for(i=0;i<x;i++)
		for(j=0;j<y;j++)
			for(k=0;k<z;k++)
			{
				data[aux++] = volume->data[i][j][k];
			}

	if ((file = H5Fcreate(newname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
	{
		fprintf(stderr, WHERESTR" unable to create the HDF5 file\n",WHEREARG);
                return -1;
	}

	dimsf[0] = (hsize_t)x;
	dimsf[1] = (hsize_t)y;
	dimsf[2] = (hsize_t)z;

	fprintf(stdout, "New data set size (%d,%d,%d)\n",x,y,z);

	if ((dataspace = H5Screate_simple(3, dimsf, NULL)) < 0)
	{
		fprintf(stderr, WHERESTR" unable to create the data space\n",WHEREARG);
                return -1;
	}

	if ((datatype = H5Tcopy(H5T_IEEE_F32LE)) < 0)
	{
                fprintf(stderr, WHERESTR" unable to create the data type \n",WHEREARG);
                return -1;
        }

    	if ((status = H5Tset_order(datatype, H5T_ORDER_LE)) < 0)
	{
                fprintf(stderr, WHERESTR" unable to set order \n",WHEREARG);
                return -1;
        }

	if (( dataset = H5Dcreate2(file, dataset_name, datatype, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
	{
                fprintf(stderr, WHERESTR" unable to create the data set \n",WHEREARG);
                return -1;
        }

    	if ((status = H5Dwrite(dataset, H5T_IEEE_F32LE, H5S_ALL, H5S_ALL, H5P_DEFAULT, data)) < 0)
	{
                fprintf(stderr, WHERESTR" unable to write data set \n",WHEREARG);
                return -1;
        }

	if (H5Sclose(dataspace) < 0)
	{
                fprintf(stderr, WHERESTR" unable to close the dataspace\n",WHEREARG);
                return -1;
        }

	if (H5Tclose(datatype) < 0)
	{
                fprintf(stderr, WHERESTR" unable to close the datatype\n",WHEREARG);
                return -1;
        }

	if (H5Dclose(dataset) < 0)
	{
                fprintf(stderr, WHERESTR" unable to close the data set\n",WHEREARG);
                return -1;
        }

	if (H5Fclose(file) < 0)
	{
                fprintf(stderr, WHERESTR" unable to close the file\n",WHEREARG);
                return -1;
        }

	free(data);
	
	return 0;
}
